package cn.cyh.queue_service.controller;

import cn.cyh.queue_service.common.Result;
import cn.cyh.queue_service.common.ResultCode;
import cn.cyh.queue_service.config.FaceRecognitionProperties;
import cn.cyh.queue_service.exception.ExternalServiceException;
import cn.cyh.queue_service.model.dto.FaceVerificationRequest;
import cn.cyh.queue_service.model.dto.FaceVerificationResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * 人脸识别代理控制器
 * 负责与人脸识别服务进行交互
 */
@RestController
@RequestMapping("/face")
@RequiredArgsConstructor
@Tag(name = "人脸识别代理", description = "人脸识别代理接口")
@Slf4j
public class FaceProxyController {

    private final RestTemplate restTemplate;
    private final FaceRecognitionProperties faceProperties;
    
    private static final String SERVICE_NAME = "face-recognition";
    private static final int MAX_RETRIES = 3;

    /**
     * 验证人脸特征
     * @param request 人脸验证请求
     * @return 验证结果
     */
    @PostMapping("/verify")
    @Operation(summary = "人脸验证", description = "验证用户人脸与注册的人脸是否匹配")
    @Retryable(
        value = {RestClientException.class, ResourceAccessException.class},
        maxAttempts = 3,
        backoff = @Backoff(delay = 500, multiplier = 2)
    )
    public Result<FaceVerificationResponse> verifyFace(@RequestBody FaceVerificationRequest request) {
        log.info("接收到人脸验证请求，用户ID：{}", request.getUserId());
        
        try {
            HttpHeaders headers = createHeaders();
            HttpEntity<FaceVerificationRequest> entity = new HttpEntity<>(request, headers);
            
            ResponseEntity<Result<FaceVerificationResponse>> responseEntity = restTemplate.exchange(
                    faceProperties.getBaseUrl() + "/api/verify",
                    HttpMethod.POST,
                    entity,
                    new ParameterizedTypeReference<Result<FaceVerificationResponse>>() {}
            );
            
            if (responseEntity.getStatusCode().is2xxSuccessful() && responseEntity.getBody() != null) {
                Result<FaceVerificationResponse> result = responseEntity.getBody();
                log.info("人脸验证请求成功，结果：{}", result);
                return result;
            } else {
                log.error("人脸验证请求失败，HTTP状态码：{}", responseEntity.getStatusCode());
                throw new ExternalServiceException(
                    "人脸验证服务返回非成功状态码: " + responseEntity.getStatusCode(),
                    SERVICE_NAME,
                    ResultCode.FACE_SERVICE_ERROR,
                    0,
                    MAX_RETRIES
                );
            }
        } catch (RestClientException e) {
            log.error("人脸验证请求异常", e);
            throw e; // 让@Retryable处理
        } catch (Exception e) {
            log.error("人脸验证请求发生未预期异常", e);
            throw new ExternalServiceException(
                "人脸验证请求失败: " + e.getMessage(),
                e,
                SERVICE_NAME,
                ResultCode.FACE_SERVICE_ERROR,
                0,
                MAX_RETRIES
            );
        }
    }
    
    /**
     * 人脸验证失败恢复处理
     */
    @Recover
    public Result<FaceVerificationResponse> recoverVerifyFace(RestClientException e, FaceVerificationRequest request) {
        log.error("人脸验证请求重试{}次后仍然失败", MAX_RETRIES, e);
        throw new ExternalServiceException(
            "人脸验证服务不可用，请稍后再试",
            e,
            SERVICE_NAME,
            ResultCode.FACE_SERVICE_ERROR,
            MAX_RETRIES,
            MAX_RETRIES
        );
    }

    /**
     * 注册人脸特征
     * @param userId 用户ID
     * @param file 人脸图片
     * @return 注册结果
     */
    @PostMapping("/register")
    @Operation(summary = "注册人脸", description = "注册用户人脸特征")
    @Retryable(
        value = {RestClientException.class, ResourceAccessException.class},
        maxAttempts = 3,
        backoff = @Backoff(delay = 500, multiplier = 2)
    )
    public Result<String> registerFace(
            @RequestParam("userId") @Parameter(description = "用户ID") String userId,
            @RequestParam("file") @Parameter(description = "人脸图片") MultipartFile file) {
        
        log.info("接收到人脸注册请求，用户ID：{}", userId);
        
        try {
            HttpHeaders headers = createHeaders();
            headers.setContentType(MediaType.MULTIPART_FORM_DATA);
            
            Map<String, Object> body = new HashMap<>();
            body.put("userId", userId);
            body.put("file", file.getResource());
            
            HttpEntity<Map<String, Object>> entity = new HttpEntity<>(body, headers);
            
            ResponseEntity<Result<String>> responseEntity = restTemplate.exchange(
                    faceProperties.getBaseUrl() + "/extract",
                    HttpMethod.POST,
                    entity,
                    new ParameterizedTypeReference<Result<String>>() {}
            );
            
            if (responseEntity.getStatusCode().is2xxSuccessful() && responseEntity.getBody() != null) {
                Result<String> result = responseEntity.getBody();
                log.info("人脸注册请求成功，结果：{}", result);
                return result;
            } else {
                log.error("人脸注册请求失败，HTTP状态码：{}", responseEntity.getStatusCode());
                throw new ExternalServiceException(
                    "人脸注册服务返回非成功状态码: " + responseEntity.getStatusCode(),
                    SERVICE_NAME,
                    ResultCode.FACE_SERVICE_ERROR,
                    0,
                    MAX_RETRIES
                );
            }
        } catch (RestClientException e) {
            log.error("人脸注册请求异常", e);
            throw e; // 让@Retryable处理
        } catch (Exception e) {
            log.error("人脸注册请求发生未预期异常", e);
            throw new ExternalServiceException(
                "人脸注册请求失败: " + e.getMessage(),
                e,
                SERVICE_NAME,
                ResultCode.FACE_SERVICE_ERROR,
                0,
                MAX_RETRIES
            );
        }
    }
    
    /**
     * 人脸注册失败恢复处理
     */
    @Recover
    public Result<String> recoverRegisterFace(RestClientException e, String userId, MultipartFile file) {
        log.error("人脸注册请求重试{}次后仍然失败", MAX_RETRIES, e);
        throw new ExternalServiceException(
            "人脸注册服务不可用，请稍后再试",
            e,
            SERVICE_NAME,
            ResultCode.FACE_SERVICE_ERROR,
            MAX_RETRIES,
            MAX_RETRIES
        );
    }

    /**
     * 删除人脸特征数据
     * @param userId 用户ID
     * @return 删除结果
     */
    @DeleteMapping("/delete")
    @Operation(summary = "删除人脸数据", description = "删除用户的人脸特征数据")
    @Retryable(
        value = {RestClientException.class, ResourceAccessException.class},
        maxAttempts = 3,
        backoff = @Backoff(delay = 500, multiplier = 2)
    )
    public Result<String> deleteFaceData(@RequestParam("userId") @Parameter(description = "用户ID") String userId) {
        log.info("接收到人脸数据删除请求，用户ID：{}", userId);
        
        try {
            HttpHeaders headers = createHeaders();
            HttpEntity<Void> entity = new HttpEntity<>(headers);
            
            Map<String, String> uriVariables = Collections.singletonMap("userId", userId);
            
            ResponseEntity<Result<String>> responseEntity = restTemplate.exchange(
                    faceProperties.getBaseUrl() + "/api/delete/{userId}",
                    HttpMethod.DELETE,
                    entity,
                    new ParameterizedTypeReference<Result<String>>() {},
                    uriVariables
            );
            
            if (responseEntity.getStatusCode().is2xxSuccessful() && responseEntity.getBody() != null) {
                Result<String> result = responseEntity.getBody();
                log.info("人脸数据删除请求成功，结果：{}", result);
                return result;
            } else {
                log.error("人脸数据删除请求失败，HTTP状态码：{}", responseEntity.getStatusCode());
                throw new ExternalServiceException(
                    "人脸数据删除服务返回非成功状态码: " + responseEntity.getStatusCode(),
                    SERVICE_NAME,
                    ResultCode.FACE_SERVICE_ERROR,
                    0,
                    MAX_RETRIES
                );
            }
        } catch (RestClientException e) {
            log.error("人脸数据删除请求异常", e);
            throw e; // 让@Retryable处理
        } catch (Exception e) {
            log.error("人脸数据删除请求发生未预期异常", e);
            throw new ExternalServiceException(
                "人脸数据删除请求失败: " + e.getMessage(),
                e,
                SERVICE_NAME,
                ResultCode.FACE_SERVICE_ERROR,
                0,
                MAX_RETRIES
            );
        }
    }
    
    /**
     * 人脸数据删除失败恢复处理
     */
    @Recover
    public Result<String> recoverDeleteFaceData(RestClientException e, String userId) {
        log.error("人脸数据删除请求重试{}次后仍然失败", MAX_RETRIES, e);
        throw new ExternalServiceException(
            "人脸数据删除服务不可用，请稍后再试",
            e,
            SERVICE_NAME,
            ResultCode.FACE_SERVICE_ERROR,
            MAX_RETRIES,
            MAX_RETRIES
        );
    }

    /**
     * 检查人脸识别服务健康状态
     * @return 健康状态
     */
    @GetMapping("/health")
    @Operation(summary = "健康检查", description = "检查人脸识别服务的健康状态")
    @Retryable(
        value = {RestClientException.class, ResourceAccessException.class},
        maxAttempts = 3,
        backoff = @Backoff(delay = 500, multiplier = 2)
    )
    public Result<String> checkHealth() {
        log.info("接收到人脸识别服务健康检查请求");
        
        try {
            HttpHeaders headers = createHeaders();
            HttpEntity<Void> entity = new HttpEntity<>(headers);
            
            ResponseEntity<Result<String>> responseEntity = restTemplate.exchange(
                    faceProperties.getBaseUrl() + "/health",
                    HttpMethod.GET,
                    entity,
                    new ParameterizedTypeReference<Result<String>>() {}
            );
            
            if (responseEntity.getStatusCode().is2xxSuccessful() && responseEntity.getBody() != null) {
                Result<String> result = responseEntity.getBody();
                log.info("人脸识别服务健康检查成功，结果：{}", result);
                return result;
            } else {
                log.error("人脸识别服务健康检查失败，HTTP状态码：{}", responseEntity.getStatusCode());
                throw new ExternalServiceException(
                    "人脸识别服务健康检查返回非成功状态码: " + responseEntity.getStatusCode(),
                    SERVICE_NAME,
                    ResultCode.FACE_SERVICE_ERROR,
                    0,
                    MAX_RETRIES
                );
            }
        } catch (RestClientException e) {
            log.error("人脸识别服务健康检查异常", e);
            throw e; // 让@Retryable处理
        } catch (Exception e) {
            log.error("人脸识别服务健康检查发生未预期异常", e);
            throw new ExternalServiceException(
                "人脸识别服务健康检查失败: " + e.getMessage(),
                e,
                SERVICE_NAME,
                ResultCode.FACE_SERVICE_ERROR,
                0,
                MAX_RETRIES
            );
        }
    }
    
    /**
     * 健康检查失败恢复处理
     */
    @Recover
    public Result<String> recoverCheckHealth(RestClientException e) {
        log.error("人脸识别服务健康检查重试{}次后仍然失败", MAX_RETRIES, e);
        throw new ExternalServiceException(
            "人脸识别服务不可用，请稍后再试",
            e,
            SERVICE_NAME,
            ResultCode.FACE_SERVICE_ERROR,
            MAX_RETRIES,
            MAX_RETRIES
        );
    }

    /**
     * 创建HTTP请求头
     * @return HTTP请求头
     */
    private HttpHeaders createHeaders() {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("X-API-Key", faceProperties.getApiKey());
        headers.set("X-API-Secret", faceProperties.getApiSecret());
        return headers;
    }
} 